#include "board_com.h"
#include "damiao.h"
#include "dji.h"
#include "rtdef.h"
#include <rtthread.h>
#include <rtdevice.h>
#include "can_common.h"

#define CAN1_DEV_NAME       "can1"      /* CAN 设备名称 */
#define CAN2_DEV_NAME       "can2"

#define LOG_TAG              "can"
#define LOG_LVL              LOG_LVL_DBG
#include <ulog.h>

static struct rt_semaphore rx1_sem;     /* 用于接收消息的信号量 */
static struct rt_semaphore rx2_sem;



rt_device_t can1_bus;            /* CAN 设备句柄 */
rt_device_t can2_bus;


struct rt_can_msg rx1msg = {0};
struct rt_can_msg rx2msg = {0};



/* 接收数据回调函数 */
static rt_err_t can_rx1_call(rt_device_t dev, rt_size_t size)
{
    /* CAN 接收到数据后产生中断，调用此回调函数，然后发送接收信号量 */
    rt_sem_release(&rx1_sem);

    return RT_EOK;
}

static rt_err_t can_rx2_call(rt_device_t dev, rt_size_t size)
{
    /* CAN 接收到数据后产生中断，调用此回调函数，然后发送接收信号量 */
    rt_sem_release(&rx2_sem);

    return RT_EOK;
}

static void can_rx1_thread(void *parameter)
{
    /* hdr 值为 - 1，表示直接从 uselist 链表读取数据 */
    rx1msg.hdr_index = -1;

    /* 设置接收回调函数 */
    rt_device_set_rx_indicate(can1_bus, can_rx1_call);

    while (1)
    {
        /* 阻塞等待接收信号量 */
        if(rt_sem_take(&rx1_sem, RT_WAITING_FOREVER)==RT_EOK){
            rt_device_read(can1_bus, 0,&rx1msg,sizeof(rx1msg));
            DecodeDJIMotor(rx1msg);
            DMMotorDecode(rx1msg);
            board_recv(rx1msg);
        }
        //LOG_D("can1 receive data\n");
        rt_thread_mdelay(1);
    }
}

static void can_rx2_thread(void *parameter)
{
    /* hdr 值为 - 1，表示直接从 uselist 链表读取数据 */
    rx2msg.hdr_index = -1;


    /* 设置接收回调函数 */                                                     
    rt_device_set_rx_indicate(can2_bus, can_rx2_call);

    while (1)
    {
        /* 阻塞等待接收信号量 */
        if (rt_sem_take(&rx2_sem, RT_WAITING_FOREVER)==RT_EOK)
        {
            rt_device_read(can2_bus, 0,&rx2msg,sizeof(rx2msg));
            DecodeDJIMotor(rx2msg);
            DMMotorDecode(rx2msg);
            
        }
        //LOG_D("can2 receive data\n");
        rt_thread_mdelay(1);
    }
}

int can_init(void)
{
    rt_err_t res;
    rt_size_t  size;
    rt_thread_t thread;
    /* 查找 CAN 设备 */
    can1_bus = rt_device_find(CAN1_DEV_NAME);
    if (!can1_bus)
    {
        LOG_E("CAN device %s not found!",CAN1_DEV_NAME);
    }
    can2_bus = rt_device_find(CAN2_DEV_NAME);
    if (!can2_bus)
    {
        LOG_E("CAN device %s not found!",CAN1_DEV_NAME);
    }

    /* 初始化 CAN 接收信号量 */
    rt_sem_init(&rx1_sem, "rx1_sem", 0, RT_IPC_FLAG_FIFO);
    rt_sem_init(&rx2_sem, "rx2_sem", 0, RT_IPC_FLAG_FIFO);

    /* 以中断接收及发送方式打开 CAN 设备 */
    res = rt_device_open(can1_bus, RT_DEVICE_FLAG_INT_TX | RT_DEVICE_FLAG_INT_RX);
    /* 设置 CAN 通信的波特率为 500kbit/s*/
    res = rt_device_control(can1_bus, RT_CAN_CMD_SET_BAUD, (void *)CAN1MBaud);
    /* 设置 CAN 的工作模式为正常工作模式 */
    res = rt_device_control(can1_bus, RT_CAN_CMD_SET_MODE, (void *)RT_CAN_MODE_NORMAL);
    
    struct rt_can_filter_item items[1] =
    {
        RT_CAN_FILTER_ITEM_INIT(0x00, 0, 0, 0, 0x00),
        /* 过滤 ID 为 0x01,match ID:0x100~0x1ff，hdr 为 - 1，设置默认过滤表 */
    };
    struct rt_can_filter_config cfg = {1, 1, items}; /* 一共有 1 个过滤表 */
    /* 设置硬件过滤表 */
    res = rt_device_control(can1_bus, RT_CAN_CMD_SET_FILTER, &cfg);


    res = rt_device_open(can2_bus, RT_DEVICE_FLAG_INT_TX | RT_DEVICE_FLAG_INT_RX);
    /* 设置 CAN 通信的波特率为 500kbit/s*/
    res = rt_device_control(can2_bus, RT_CAN_CMD_SET_BAUD, (void *)CAN1MBaud);
    /* 设置 CAN 的工作模式为正常工作模式 */
    res = rt_device_control(can2_bus, RT_CAN_CMD_SET_MODE, (void *)RT_CAN_MODE_NORMAL);    

    res = rt_device_control(can2_bus, RT_CAN_CMD_SET_FILTER, &cfg);


    RT_ASSERT(res == RT_EOK);

    /* 创建数据接收线程 */
    thread = rt_thread_create("can_rx1", can_rx1_thread, RT_NULL, 1024, 20, 10);
    if (thread != RT_NULL)
    {
        rt_thread_startup(thread);
    }
    else
    {
        LOG_E("create can_rx1 thread failed!\n");
    }

    thread = rt_thread_create("can_rx2", can_rx2_thread, RT_NULL, 1024, 20, 10);
    if (thread != RT_NULL)
    {
        rt_thread_startup(thread);
    }
    else
    {
        LOG_E("create can_rx2 thread failed!\n");
    }

    return RT_EOK;
}
/* 导出到 msh 命令列表中 */
INIT_APP_EXPORT(can_init);
